CHAPTER 13
Design Decisions
Now that you’ve become familiar with the various tools in the XMPP toolkit, let’s start
to think about how you can use those tools to build an XMPP application (or XMPPenable  an  existing  application).  In  this  chapter,  we  explore  some  of  the  thought
processes underlying successful application development with XMPP. Then in Chapter 14, we illustrate these principles by building an application from the ground up.
Is XMPP the Right Choice?
Like any technology, XMPP has strengths and weaknesses. As legendary Internet protocol designer Marshall Rose once put it, you can build a good helicopter or you can
build a good submarine, but you can’t build something that is both a good helicopter
and a good submarine. Trying to use the same tool to solve every problem usually ends
in disaster.
As we mentioned before, XMPP was designed to transmit numerous small snippets of
XML data over a decentralized network in close to real time, with built-in presence and
straightforward  federation.  This  means  that  XMPP  is  not  a  panacea  for  all  Internet
usages and, thankfully, the Internet already has time-tested technologies you can use
instead  for  other  tasks:  HTTP/HTML,  BitTorrent,  Real-time  Transport  Protocol,
SMTP/POP/IMAP, Usenet, etc.
So when is XMPP a good choice? Here are some guidelines:
• When you need information about network availability, i.e., presence
• When you need to deliver “just-in-time” alerts and notifications instead of con
tinually polling for updates
• When you need channel encryption, strong authentication, and trusted identities
• When you need communication among a distributed network of entities or servers
• When  you  need  a  relatively  simple  signaling  channel  to  set  up  multimedia
interactions
199
• When you need the extensibility of XML for custom payloads
• When you want to tap into the large user base on the XMPP network
These considerations have led many cutting-edge software developers to incorporate
XMPP into their applications. As of this writing, XMPP technologies seem to be especially popular in the following domains:
Social networking
The main attraction here is that XMPP overcomes the serious scaling problems
associated with constantly polling for updated information. As we discussed in
Chapter 8, it’s much more efficient to treat microblogging, location sharing, and
social  music  services  as  forms  of  on-demand  micromessaging  than  as  dynamic
websites that must be continually polled for updates.
Cloud computing and machine-to-machine communication
In the emerging “Internet of Things,” it makes a lot of sense to use real-time messaging to coordinate activities between a distributed network of entities, especially
because presence information and service discovery can reveal which entities are
both available on the network and capable of handling particular tasks.
Voice, video, and other multimedia sessions
XMPP is not optimized for transferring bandwidth-heavy data such as voice and
video, but it is nearly ideal for managing such transfers. Existing session management technologies do not natively incorporate three key features of XMPP: presence  information,  trusted  identities,  and  straightforward  federation  between
domains. Presence enables the same kind of fluid communication that is familiar
from instant messaging (no more voicemail!), trusted identities significantly reduce
the possibility of spam, and federation makes it possible to finally connect a large
number of separate silos and thus increase the power of the Internet’s real-time
communications network.
How do you implement these and other application types? Usually you won’t build
your entire application from scratch; instead, you’ll mix and match existing code with
your own custom code. That means you will install, download, embed, or otherwise
employ one or more of the servers, libraries, clients, and other codebases released by
various  participants  in  the  XMPP  developer  community.  Then  you’ll  build  on  that
foundation to add your own special features. For example, you might write a client
plug-in, a bot, a server module, or an external component that will integrate with the
infrastructure you’ve installed. If you get really serious, you might even write your own
custom client or server, although that’s a bigger task. In any case, no matter how you
proceed, you’ll need to know how the XMPP developer community works, and how
to work with that community, so let’s delve into that topic next.
200 | Chapter 13: Design Decisions
How the XMPP Community Works
In order to build XMPP applications, it helps to understand how the XMPP developer
community is structured so that you can get the most out of community-generated
software, build your own software, and define XMPP extensions.
Perhaps the most important lesson to learn about the XMPP developer community is
that it is extremely diverse, and it has become more and more diverse over the years.
In the beginning, there was one Jabber project: the open source jabberd server created
by Jeremie Miller. Immediately, other open source developers contributed to Jeremie’s
server project, but they also wrote clients for Windows and Mac and Linux that would
connect to jabberd, server modules (generically called components) that would work
with jabberd, and code libraries for Perl and Java and many other languages that would
enable  other  people  to  create  additional  code  projects.  So,  right  from  the  start,  the
community was focused not on a single codebase (as with, say, the Apache web server),
but on a technology ecosystem.
Since 1999, that ecosystem has continued to grow and change. Developers have come
and gone, early projects disappeared, new projects emerged to take their place, commercial companies and service providers built their own implementations, additional
open source server projects came into being, and deployment of all this software became
almost commonplace on the Internet. As a result, the XMPP community contains many
participants:
• Open source projects and individual developers
• Small consultancies that support particular codebases or offer XMPP expertise in
certain domains (e.g., for mobile devices)
• Midsize software development shops
• Large hardware and software companies such as Apple, Cisco, Nokia, and Sun
• Service providers such as Google, LiveJournal, DreamHost, and GMX
• Businesses, universities, and other operators of XMPP services
• The XMPP Standards Foundation (XSF), which loosely coordinates all of this ac
tivity but primarily focuses on standardization of the XMPP protocols
Just as XMPP itself is a decentralized technology, so too is the community decentralized.
There is no one central location where all of these projects, companies, and other parties
host their code, manage their projects, help their users, or share operational experience.
Instead,  each  project  has  its  own  website,  code  repository,  and  communication
channels.
Paradoxically, this decentralized approach has not prevented the community from remaining  relatively  coherent  in  its  priorities  and  direction.  Given  its  focus  on  rough
consensus and running code, the various entities in the XMPP community have two
primary  connection  points:  the  standardization  of  the  XMPP  protocols,  and  the
How the XMPP Community Works
| 201
day-to-day operation of the XMPP communications network. If a new server joins the
network but it doesn’t quite interoperate with existing software and services, you can
be sure that the developers of that server will quickly receive bug reports from interested
coders in the community. Likewise, the busiest discussion venue run by the XSF is the
standards@xmpp.org mailing list, where hundreds of developers define new protocol
extensions and work to clarify the subtleties of older protocols. (The XSF also runs
specialized discussion lists and chat rooms for PubSub, Jingle, BOSH, MUC, social
networking, mobile applications, operational challenges, and other such topics; consult http://xmpp.org for a full list.)
The fact that the XMPP community is so decentralized can be a bit disorienting at first.
For example, you may need to hunt around for a while to find a codebase that meets
your needs or a software developer who can solve your problem. On the other hand,
this decentralization means that it is quite easy to contribute new code, create new
projects, and join the developer community (it also means that problems in one XMPPrelated project don’t infect all the others, leading to an almost Darwinian survival of
the fittest over time).
In the following sections, we talk about how to make use of the many existing software
codebases,  design  and  implement  new  code,  and  define  new  XMPP  extensions  if
needed.
Writing XMPP Software
Whether you want to extend an existing application or service to use XMPP, or you
want to build an XMPP-based application from the ground up, your adventure will
always begin with finding the right ingredients to make your XMPP recipe. You will be
able to use some of these ingredients directly off-the-shelf, others will require making
some extensions or modifications, and some other parts will have to be created from
scratch, either with or without the use of commonly available libraries and SDKs. In
this section, we delve deeper into the various aspects involved in building your own
XMPP application.
Mixing, Matching, and Extending Existing XMPP Software
In order to build an XMPP application, you will need a few moving parts. Some of these
you  will  be  able  to  use  as-is,  and  others  may  require  tailoring  to  meet  your  needs.
However, most XMPP applications consist of the following parts:
An XMPP server
Many open source and commercial XMPP server codebases exist, of which a few
are  described  briefly  in  “Servers”  on  page  253.  If  you  want  to  deploy  a  serious
XMPP application, you’ll need to install one of these codebases and run it at your
own domain. (The alternative is to run a lightweight bot at one of the public XMPP
services, such as Google Talk or jabber.org, but if you do so, you run the risk of
202 | Chapter 13: Design Decisions
being rate-limited or otherwise restricted by the policies in force at that service.)
Existing server projects can typically be extended with extra, custom functionality
through server-side modules or add-on components (we talk about these a bit more
later in this chapter). Although not very common, it could even happen that your
requirements cannot be met by using components or server-side modules. In that
case, you may choose to modify the server software (if the license allows it), or even
developer your own server implementation. Examples of organizations that chose
to build their own XMPP servers are LiveJournal (which released its software as
the djabberd codebase) and the Google Talk service.
An XMPP client
Some XMPP-based applications are built around a particular XMPP client. The
association between a client and a service can take the form of an existing IM client
that  has  been  extended  to  suit  your  needs  using  plug-ins  or  adaptations  to  the
original codebase. However, it is not uncommon that your application will require
a dedicated, new client for what you want to achieve. For example, when building
a networked chess game application, you will not start from an IM client; instead,
you will create your own application and add XMPP client functionality to it. In
that case, you will need to write your own client, possibly making use of one of the
many available XMPP client libraries.
Integration with existing infrastructure
In some cases, your application will not be a strict client-server application. Rather,
you will integrate with existing infrastructure, such as a database, a content management system, or a distributed computing platform. In this case, XMPP technologies will form the “communications glue” among various entities within your
infrastructure, and you may not even need a single server (e.g., each entity could
run its own lightweight mini-server and then federate with the other entities).
Because of the decentralized nature of XMPP technologies and the modular approach
taken by many XMPP developers, you can mix and match implementations of all your
parts. For example, you might use one of the open source XMPP servers, but write your
own custom XMPP client. In the next section, we explore what is needed to develop
your own XMPP software.
Client Extension, Bot, Component, or Server Module?
When it comes to writing your own XMPP software, there are several approaches that
may fit your needs. Often, there is more than one way to reach your goal, so which is
best? This section addresses some of the design trade-offs you may face.
A first question that may arise is: Should I put most of my extensions on the server, or
should I put the code in the client? The Jabber philosophy has always been to take as
much burden as possible from the client and put it in the server. This approach has a
number of advantages:
Writing XMPP Software | 203
• By keeping the clients as simple as possible, you are making it very easy for another
client to be extended or even make use of your application, as the changes that
need to be done on the client side are minimal.
• The server often has easy access to information that is hard to retrieve from the
client. Moreover, it is a lot easier, safer, and more robust to adapt server-side information from the server software, which has direct access to the data.
Because of this philosophy, XMPP server implementations tend to be architected in a
more modular fashion than XMPP clients. You will find that you can much more easily
extend XMPP servers using components and plug-ins than you can extend most existing
XMPP clients.
When moving the functionality out of the client, you are still left with several options
to provide your services from the server side. The easiest way to provide services over
XMPP is to create a bot. A bot is a program that logs into a server like a normal client,
with a regular JabberID. Other clients typically add this bot to their roster, and a user
can then send it messages, to which the bot responds. Such a bot can also react to the
presence changes of the people in its roster. For example, there might be a bot called
mapbot@wonderland.lit that subscribes to all PEP geolocation changes (see Chapter 8)
of all clients in its roster. Whenever it receives geolocation information about one of
its contacts, it draws a marker on a map, served on some web page. Thanks to the
availability of XMPP libraries for a variety of high-level languages, creating a bot can
be a very easy way to do interesting things with XMPP in very little time (and code).
The fact that bots can connect to any deployed XMPP server makes them very flexible,
and allows virtually anyone to run a bot without having to set up a server themselves.
Although bots can yield some interesting XMPP applications, sometimes their capabilities can be restricting because they are bound to one specific JID on a server. This
is where components come into play. As discussed in Chapter 12, when a component
connects to a server, it is assigned a subdomain of the server. Every stanza that is destined for that subdomain is then delivered to the component, which can act upon it.
For example, in Chapter 7, we talked about multiuser chat components getting assigned
a subdomain (e.g., conference.wonderland.lit); when there is an incoming message
for trial@conference.wonderland.lit, the server directly routes it to the MUC component without looking at the node part (in this case, trial) of the JID. The MUC component treats the node part of the JID as a room name, and posts the message to the
trial room.
Because the server leaves all internal processing of the subdomain to the component,
it also does not keep track of any roster for a component. Since it routes all stanzas to
the component directly, including presence stanzas, it is the component’s responsibility
to maintain a roster based on incoming presence subscription stanzas (if it chooses to).
This technique increases the complexity of your implementation, but it also increases
the scalability of your implementation because you are no longer limited by a particular
server  codebase  (which  typically  is  architected  to  handle  thousands  of  concurrent
204 | Chapter 13: Design Decisions
sessions for entities with relatively small rosters, not one session for an entity with an
extremely large roster). Some applications that started out with a bot approach have
found it necessary to switch to a server component approach when their bot became
very popular.
The extra control of a component comes with a price, though. In order for a component
to connect to a server, the server needs to be specially configured to allow this component  to  connect  as  the  handler  for  a  specific  subdomain  of  the  server.  Because  a
component  needs  explicit  permissions  from  the  server,  not  everyone  can  just  run  a
component on every server. This makes components less flexible than bots. However,
because components use a standardized protocol to connect to a server, as we discussed
in Chapter 12, one component can be used in combination with many different XMPP
server  codebases,  thus  reducing  the  risk  of  being  “locked  in”  to  a  particular  server
project or product.
Although server components give you more control than bots, at the far end of the
scale, there are applications for which they also can be too limiting for your application.
For example, your application may need direct access to server internals (such as direct
access to the rosters from all users), or you may be dealing with performance-critical
applications  where  a  network  connection  between  the  server  and  your  component
would become a bottleneck. In this case, your application will need to directly tap into
the server implementation. The most common approach if you need this much control
is to write a server module that is loaded into the server and that gives you direct access
to the information you need. However, having full control over the server means that
your application will be tied to a particular server implementation. This means that
you will have much less flexibility in changing servers later, and that the possibilities
for reuse will be significantly reduced.
Rolling Your Own Client or Server
In some cases, extending an existing software codebase might not be enough for your
needs. For example, existing clients that could otherwise help solve your problem might
be focused on one use of XMPP (for example, instant messaging), whereas your application targets a completely different use case. In this case, you will need to design your
own client, tailored to your needs. Aside from purely functional reasons, other considerations may apply, such as license costs.
If you want to build your own software, you are still left with the choice to build it on
top of one of the many existing XMPP libraries (see “Libraries” on page 258) or to
build your solution from the ground up.
Building your own XMPP client or server from scratch requires a considerable amount
of low-level functionality. In many cases, this functionality is supported by external
libraries, or in some cases provided by the standard library of the programming language you are targeting. If you are considering building your own solution, you should
look for the following low-level functionality:
Writing XMPP Software | 205
XML parsing
Because XMPP is an XML-based protocol, an XMPP client or server will obviously
need to do some XML parsing. Since XMPP uses a strict subset of the full XML
specification, some of the complexity involved in parsing XML can be avoided.
Many off-the-shelf XML libraries exist, and many languages even come with XMPP
support in their built-in libraries. The most important part to keep in mind is that
the XML parser needs to be incremental, and needs to be able to handle incomplete
data. An XMPP stream becomes a full XML document only after the XMPP session
is over, and the actual XML elements (i.e., the XMPP stanzas) can be delivered in
chunks due to network constraints. This functionality is typically available in most
stream-based XML parsers (e.g., SAX).
DNS SRV lookups
Many libraries provide an easy interface for doing lookups of host addresses by
domain  name.  However,  in  order  to  make  deployment  as  flexible  as  possible,
XMPP allows server administrators to host an XMPP service for a certain domain
on a different host than the main domain host. Chapter 12 describes how both
clients and servers use DNS SRV lookups to find out the hosts serving XMPP for
a specific domain. This advanced DNS query functionality is often omitted in DNS
libraries (although it is becoming more common all the time).
Secure TLS connections
Although secure connections often are not very crucial in many protocols, they
play a very important role in the XMPP world. At the time of this writing, some
key XMPP deployments have explicitly disabled support for nonsecured connections, and we expect many (if not all) services to follow suit at some point. As a
result, supporting secure connections using Transport Layer Security (as described
in  Chapter  12)  is  practically  a  hard  requirement  when  building  an  XMPP
application.
Support for channel encryption can be implemented using external dedicated libraries such as OpenSSL and GnuTLS, or by using higher-level toolkit libraries.
Many higher-level languages even provide support for TLS (or, equivalently, SSL)
in their standard networking libraries. However, keep in mind that many of the
higher-level libraries only provide TLS in the form of “secure sockets,” i.e., sockets
that securely connect to a target host using channel encryption at a specified port
(e.g., 443 for HTTPS). By contrast, XMPP starts with an unencrypted connection,
and then dynamically upgrades that connection to an encrypted connection using
the “STARTTLS” feature of Transport Layer Security. If your library supports only
sockets that are encrypted from the initial connection, you may need to write your
own TLS support.
SASL authentication
As discussed in Chapter 12, XMPP uses the Simple Authentication and Security
Layer (SASL) framework for standards-based authentication between clients and
servers. By implementing only the most basic SASL authentication mechanisms
206 | Chapter 13: Design Decisions
Internationalization
(e.g., PLAIN and DIGEST-MD5) in your software, you can support authentication
for any XMPP-compliant entity. These basic mechanisms are simple enough that
they can be implemented without the need for external libraries. However, for more
advanced authentication mechanisms (such as Kerberos using the GSSAPI mechanism), it is probably more convenient to use dedicated SASL libraries (such as
Cyrus SASL or GNU SASL).
In order to support non-ASCII characters, the XMPP protocol requires UTF-8 encoding for XMPP streams (see [RFC 3629]). As a result, typically there is no need
for special text handling or conversions within an XMPP application. The only part
that might be affected is the user interface, which obviously needs to be able to
handle international character input and output, as well as encode it accordingly.
Besides the actual XMPP stream, international characters can also appear in JabberIDs. Since JIDs are used to address entities on the XMPP network, they need
special treatment with respect to international characters. More specifically, they
need to be normalized according to a set of well-defined string preparation rules
called “stringprep,” as defined in [RFC 3454]. These rules handle, amongst other
things, case-folding (which is the Unicode equivalent of case-insensitivity for ASCII
characters), as well as transforming the domain part of the JID into standard resolvable domains. This is typically done using the GNU Internationalized Domain
Names (IDN) Library.
Extending XMPP
XMPP was designed to be extended—after all, the “X” in both XMPP and XML stands
for  “extensible”!  Over  the  years,  the  XMPP  developer  community  has  built  a  long
“runway” of XMPP extensions, making it possible for you to create lots of interesting
applications with XMPP. Usually you can just mix and match existing extensions to
build the functionality you need. However, sometimes the feature you need in your
application is not yet defined in any of the existing extensions. In this section, we delve
into XMPP extensibility by showing you how to define your own custom XMPP extensions, and even publish them as freely available specifications for use by the entire
community.
How to Design Custom Extensions
Extensibility is really quite easy: just create your own XML data structure and associated namespace, and then place it into an XMPP message, presence, or IQ stanza.
For  example,  let’s  say  that  you  have  built  an  online  reading  club  and  you  want  to
exchange information about books so that users of your service can do things like share
recommendations. Scanning the existing XMPP extensions, you don’t find anything
Extending XMPP | 207
that meets your needs, so you decide to define a new XML format that looks something
like this:
<message>
  <bookinfo xmlns="http://example.com/schemas/bookinfo">
    <title>XMPP: The Definitive Guide</title>
    <subtitle>Building Real-Time Applications with Jabber Technologies</subtitle>
    <isbn>9780596521264</isbn>
    <note>One of my favorite books!</note>
  </bookinfo>
</message>
A custom format like this is very much preferable to overloading of existing XMPP data
structures, such as in the negative example shown here:
<message>
  <body>One of my favorite books!</body>
  <subject>XMPP: The Definitive Guide; 
           Building Real-Time Applications with Jabber Technologies</subject>
  <thread>9780596521264</thread>
</message>
The contrast between these two examples illustrates one of the key principles of protocol design in the Jabber community: the core XMPP specifications are sacred. Any
feature you might need can probably be defined farther up the XMPP protocol stack
than in the core streaming, messaging, and presence layer (and if you think that you
need to modify the core layer, think again). Instead, focus higher up the stack by defining  new  namespaces  that  can  be  included  in  message  or  IQ  stanzas  (and,  rarely,
presence stanzas).
Another key principle is to keep presence as small and focused as possible. It’s easy to
think  that  presence  is  a  good  model  for  sending  notifications  each  time  someone’s
music player loads a new tune, including complete information about the title, performer, running time, track number, lyrics, or even associated artwork. If the listener
has 100 online friends in his roster, though, your application will result in 100 large
presence notifications every 3 or 4 minutes, which is not very network-friendly. In fact,
presence is the primary bottleneck in any messaging and presence technology, being
responsible for as much as 90% of the traffic, so it’s important to use presence only for
is  online  and  available  for
information  that  determines  whether  someone 
communication.
A third key principle is to keep XMPP clients as simple as possible (without putting
undue strain on XMPP servers). This is often a delicate balancing act. Sometimes clients
really  do  know  best  (e.g.,  about  user  preferences  or  local  network  conditions),  and
therefore need to include more complexity. Usually it is inefficient to ask servers to
complete too many tasks related to a given stanza or to perform deep packet inspection
in  order  to  route  a  message.  Clients  cannot  be  trusted  to  properly  enforce  security
policies, and therefore the server must take charge in such matters. And so on.
208 | Chapter 13: Design Decisions
Finally, it is important to reuse existing protocols where possible. Just as you would
not write your own TCP or TLS implementation to create an XMPP client (if at all
possible), it doesn’t make sense to define a new transport binding for XMPP or rip out
lower layers of the XMPP protocol stack when creating a new XMPP application. Similarly, try to embed existing data formats into XMPP rather than defining new formats.
In this sense, the “bookinfo” example we just showed you is wrongheaded because it
could  have  easily  reused  data  formats  from  the  Dublin  Core  Initiative  or  DocBook
instead of defining a new XML namespace.
For more detailed recommendations about protocol design, consult the Protocol Design
Guidelines [XEP-0134], informally known as “The Tao of XMPP.”
Standardizing New Extensions
So you’ve created a custom XMPP extension, and it’s really useful in your application.
In fact, it’s so useful that you think other developers might want to add support for it,
too. How can you advertise it to the world and receive feedback on it so that it gets
even better?
Naturally, you could just post it on your project or company website, but that won’t
necessarily result in feedback from other developers. The solution is to publish your
protocol to a centralized location where everyone who cares about XMPP technologies
can read, review, and comment on your extension: the http://xmpp.org website, run by
the XSF.
The XSF was founded in the summer of 2001 to document the core Jabber protocols
and  to  define  new  extensions  to  those  protocols.  It  does  this  through  a  developerfriendly standards process focused on a series of documents called XMPP Extension
Protocols, or XEPs. The basic idea is simple (for all the details, refer to [XEP-0001]):
1. Anyone  can  submit  a  proposal  for  an  XMPP  extension  by  sending  an  email  to
editor@xmpp.org (see [XEP-0143] for further instructions).
2. The XMPP Council, elected by the members of the XSF, determines whether to
publish a given proposal as an official XEP.
3. When an XEP is first published, it has a status of Experimental.
4. After the XEP has been discussed, improved, and hopefully implemented, it can
advance to a status of Draft.
5. Eventually, after the XEP has been implemented, deployed, and improved even
further, it can advance to a status of Final.
XEPs are discussed mainly on the standards@xmpp.org list, a high-traffic mailing list
that is the primary venue for XMPP developers to clarify existing protocols and define
new ones. If you are interested in XMPP technologies, this “standards list” is the place
to be.
Extending XMPP | 209
Unlike for-pay industry consortia, the XSF does not require monetary contributions in
order to participate in its standards process. Furthermore, the XSF’s “intellectual property rights” policy ensures that XMPP extensions are patent-free and that anyone can
implement XMPP technologies under any license they care to use for their software.
These  policies  maintain  the  legacy  of  XMPP’s  roots  in  the  open  source  Jabber
community.
What does public standardization give you that just defining a private extension does
not? Aside from the fame of authoring an official XEP and the warm glow of having
contributed something back to the community, working through the XSF’s standards
process usually results in a stronger technology, because many smart people will review
your proposal, suggest improvements, point out potential security concerns, and implement it more widely (leading to better interoperability and therefore a more powerful
network effect).
Even so, it doesn’t always make sense to standardize your custom XMPP extensions.
Perhaps they define “one-off” features that are not of general interest. Perhaps they are
part of the “special sauce” in your product and you don’t want the world to find out
about your trade secrets. Perhaps you simply don’t have the time to document how
your extension works in the rigorous way that’s usually required of protocol specifications (although the friendly folks at the XSF are always happy to help with the writing
of specifications). However, many organizations and projects that define custom extensions have found it quite beneficial to submit their extensions to the XSF for more
formal  standardization  (including  big  companies  like  Apple  and  Google),  and  you
might too.
Summary
In this chapter, we covered many of the high-level issues you may face when you set
out to build an XMPP application, including how to work with the XMPP developer
community, how to use existing code developed by that community, how to write your
own XMPP-based software, and how to define protocol extensions to XMPP. Now let’s
apply those insights by building an XMPP application from the ground up.
210 | Chapter 13: Design Decisions
